package com.example.demo.netty.customizeprotocol.coder;

import com.example.demo.netty.customizeprotocol.entity.Message;
import com.example.demo.netty.customizeprotocol.entity.MessageTypeEnum;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

import java.nio.charset.Charset;
import java.util.List;

public class MessageDecoder extends ByteToMessageDecoder {

    /**自定义协议：
     * 魔数：4字节
     * 主版本号：1字节
     * 次版本号：1字节
     * 修订版本号：1字节
     * 会话id：8字节 32位长度
     * 消息类型：1字节
     * 附加数据：不定
     *          键值对个数 2字节
     *          键长度 4字节
     *          键数据 不定
     *          值长度 4字节
     *          值数据 不定
     * 消息体长度：4字节
     * 消息体：不定
     *
     * +-------------+-------------+------------+---------------+----------------+
     * | magicNumber | mainVersion | subVersion | modifyVersion |sessionId   |
     * |   0x1314    | 1 byte      | 1 byte     |     1 byte    | "HELLO, WORLD" |
     * +-------------+-------------+------------+---------------+----------------+
     * @param channelHandlerContext
     * @param byteBuf
     * @param out
     * @throws Exception
     */
    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> out) throws Exception {
        Message message = new Message();
        message.setMagicNumber(byteBuf.readInt());// 读取魔数
        message.setMainVersion(byteBuf.readByte());// 读取主版本号
        message.setSubVersion(byteBuf.readByte());// 读取次版本号
        message.setModifyVersion(byteBuf.readByte());// 读取修订版本号
        CharSequence sessionId = byteBuf.readCharSequence(32, Charset.defaultCharset()); // 读取sessionId
        message.setSessionId(sessionId.toString());
        message.setMessageType(MessageTypeEnum.get(byteBuf.readByte()));// 读取当前的消息类型

        short attachmentSize = byteBuf.readShort();// 读取附件长度
        for (short i = 0; i < attachmentSize; i++) {
            int keyLength = byteBuf.readInt();// 读取键长度和数据
            CharSequence key = byteBuf.readCharSequence(keyLength, Charset.defaultCharset());
            int valueLength = byteBuf.readInt();// 读取值长度和数据
            CharSequence value = byteBuf.readCharSequence(valueLength, Charset.defaultCharset());
            message.addAttachment(key.toString(), value.toString());
        }
        int bodyLength = byteBuf.readInt();// 读取消息体长度和数据
        CharSequence body = byteBuf.readCharSequence(bodyLength, Charset.defaultCharset());
        message.setBody(body.toString());

        out.add(message);
    }
}
